package jdos.hardware;

import jdos.gui.Main;
import jdos.hardware.VGA_memory.VRAM;
import jdos.ints.Int10_modes;
public class VGA_draw {


    static int outWriteOff;
    public static void writeb(/*HostPt*/int address,/*Bit8u*/ int value) {
    	Main.byte_rawImageData2[outWriteOff+address] = Main.cmap[value&0xF];
    }

    public static void VGA_Draw_Linear_Line(/*Bitu*/int vidstart, int width) {

        int draw = 0;

			if (VGA.newType) {
				for (/*Bitu*/int x = 0; x < width; x++) {

					/*Bitu*/int val = VRAM.readb(((vidstart + x) >> 1));

					if ((x & 1) == 1) {
						val = val >> 4;
					} else {
						val = val & 0x0F;
					}
					writeb(draw, val);
					draw++;
				}
			} else {
				for (/*Bitu*/int x = 0; x < width; x += 8) {
					int val0 = VRAM.readb((((vidstart + x) >> 3) << 2) + 0);
					int val1 = VRAM.readb((((vidstart + x) >> 3) << 2) + 1);
					int val2 = VRAM.readb((((vidstart + x) >> 3) << 2) + 2);
					int val3 = VRAM.readb((((vidstart + x) >> 3) << 2) + 3);
					int p;

					p = (((val0 >> 7) & 0x01) << 0) | (((val1 >> 7) & 0x01) << 1) | (((val2 >> 7) & 0x01) << 2) | (((val3 >> 7) & 0x01) << 3);
					writeb(draw++, p);

					p = (((val0 >> 6) & 0x01) << 0) | (((val1 >> 6) & 0x01) << 1) | (((val2 >> 6) & 0x01) << 2) | (((val3 >> 6) & 0x01) << 3);
					writeb(draw++, p);

					p = (((val0 >> 5) & 0x01) << 0) | (((val1 >> 5) & 0x01) << 1) | (((val2 >> 5) & 0x01) << 2) | (((val3 >> 5) & 0x01) << 3);
					writeb(draw++, p);

					p = (((val0 >> 4) & 0x01) << 0) | (((val1 >> 4) & 0x01) << 1) | (((val2 >> 4) & 0x01) << 2) | (((val3 >> 4) & 0x01) << 3);
					writeb(draw++, p);

					p = (((val0 >> 3) & 0x01) << 0) | (((val1 >> 3) & 0x01) << 1) | (((val2 >> 3) & 0x01) << 2) | (((val3 >> 3) & 0x01) << 3);
					writeb(draw++, p);

					p = (((val0 >> 2) & 0x01) << 0) | (((val1 >> 2) & 0x01) << 1) | (((val2 >> 2) & 0x01) << 2) | (((val3 >> 2) & 0x01) << 3);
					writeb(draw++, p);

					p = (((val0 >> 1) & 0x01) << 0) | (((val1 >> 1) & 0x01) << 1) | (((val2 >> 1) & 0x01) << 2) | (((val3 >> 1) & 0x01) << 3);
					writeb(draw++, p);

					p = (((val0 >> 0) & 0x01) << 0) | (((val1 >> 0) & 0x01) << 1) | (((val2 >> 0) & 0x01) << 2) | (((val3 >> 0) & 0x01) << 3);
					writeb(draw++, p);
				}
			}

    }
//
    //private static /*Bit32u*/int[] FontMask={0xffffffff,0x0};
	public static void VGA_TEXT_Draw_Line(/*Bitu*/int vidstart, /*Bitu*/int line, int width, int blocks, int idx) {
		/*Bits*/int font_addr;
		int draw = 0;

		for (/*Bitu*/int i = 0; i < width; i++) {
			//640
			/*Bitu*/int chr = VRAM.readb(vidstart+0x30000 + ((i >> 3) << 1));
			/*Bitu*/int col = VRAM.readb(vidstart+0x30000 + ((i >> 3) << 1) + 1);
			/*Bitu*/int font = VGA.vga.draw.font_tables[(col >> 3) & 1].get(chr * 32 + line);
			font = (font << (i & 7)) & 0x80;
			int fg = col & 0x0F;
			int bg = col >> 4;

			boolean cursor = false;
			if (VGA.vga.draw.cursor.enabled && (cursor_count & 0x8) != 0) {
				font_addr = (VGA.vga.config.cursor_start * 2 - vidstart) >> 1;
				if (font_addr >= 0 && font_addr < (/*Bits*/int) blocks) {
					if (line >= VGA.vga.draw.cursor.sline && line <= VGA.vga.draw.cursor.eline) {
						if (i >= font_addr * 8 && i < font_addr * 8 + 8) {
							cursor = true;
						}
					}
				}
			}

			if (cursor) {
				writeb(draw, col);
			} else {
				if (font != 0) {
					writeb(draw, fg);
				} else {
					writeb(draw, bg);
				}
			}
			draw++;
		}
	}

    public static short cursor_count;
	public static void Draw() {
		try {

			/*Bitu*/int width;
			/*Bitu*/int height = Int10_modes.CurMode.vdispend;

			int blocks = 0;
			
		        int address_add = 0;
				int address_line_total = 0;
	        switch (Int10_modes.CurMode.type) {
	        case VGA.M_EGA:
	            width = 640;
	            address_add=40*16;
				address_line_total = 1;
	            break;
	        case VGA.M_TEXT:
	            blocks=80;
	            address_add=40*4;
	            width = 640; // 8 bit wide text font
				address_line_total = 16;
	            break;
	            default:
	            	width = 0;
	        }


	        int lines_total=height;

			
            cursor_count++;
			outWriteOff = 0;
			int address_line = 0;
			int address = 0;
			for (int i = 0; i < lines_total; i++) {
		        switch (Int10_modes.CurMode.type) {
		        case VGA.M_EGA:
		            VGA_Draw_Linear_Line(address, width);
		            break;
		        case VGA.M_TEXT:
		            VGA_TEXT_Draw_Line(address, address_line,width, blocks, i);
		            break;
		        }
				outWriteOff += Main.buffer_width;
//				Render.memcpy();

				address_line++;
				if (address_line >= address_line_total) {
					address_line = 0;
					address += address_add;
				}
			}
            Main.GFX_EndUpdate();
			//VGA_misc.flg = 1;
		} catch (Throwable t) {
			t.printStackTrace();
		}
	}

}
